package com.yubest.fs.service.impl;

import com.yubest.fs.FileStorage;
import com.yubest.fs.bean.*;
import com.yubest.fs.enums.StorageTypeEnum;
import com.yubest.fs.exception.StorageException;
import com.yubest.fs.service.Storage;
import org.springframework.util.StringUtils;

import java.util.Map;

/**
 * @Author hweiyu
 * @Description
 * @Date 2022/2/9 12:05
 */
public class FileStorageImpl implements FileStorage {

    /**
     * 缓存可用的文件处理器
     */
    private Map<String, AbstractStorage> storageMap;

    /**
     * 默认的文件处理器类型
     */
    private String primaryStorage;

    /**
     * 当前使用的文件处理器类型
     */
    private ThreadLocal<String> tag = new ThreadLocal<>();

    public FileStorageImpl(String primaryStorage, Map<String, AbstractStorage> storageMap) {
        this.primaryStorage = primaryStorage;
        this.storageMap = storageMap;
    }

    /**
     * 上传
     * @param bucket
     * @param fileName
     * @param contentType
     * @param payload
     * @param meta
     * @return
     */
    @Override
    public PutResponse put(String bucket, String fileName, String contentType, byte[] payload, FileMeta meta) {
        return getUseStorage().put(new PutFileRequest()
                .setBucket(bucket)
                .setFileName(fileName)
                .setContentType(contentType)
                .setPayload(payload)
                .setMeta(meta));
    }

    /**
     * 下载
     * @param bucket
     * @param filePath
     * @return
     */
    @Override
    public FileStream get(String bucket, String filePath) {
        return getUseStorage().get(new GetFileRequest()
                .setBucket(bucket)
                .setPath(filePath));
    }

    /**
     * 获取文件metadata
     * @param bucket
     * @param filePath
     * @return
     */
    @Override
    public FileMeta getMeta(String bucket, String filePath) {
        return getUseStorage().getMeta(new GetFileRequest()
                .setBucket(bucket)
                .setPath(filePath));
    }

    /**
     * 获取访问路径
     * @param bucket
     * @param filePath
     * @return
     */
    @Override
    public String getUrl(String bucket, String filePath) {
        return getUseStorage().getUrl(new GetFileRequest()
                .setBucket(bucket)
                .setPath(filePath));
    }

    /**
     * 判断文件是否存在
     * @param bucket
     * @param filePath
     * @return
     */
    @Override
    public boolean isExists(String bucket, String filePath) {
        return getUseStorage().isExists(new GetFileRequest()
                .setBucket(bucket)
                .setPath(filePath));
    }

    /**
     * 删除
     * @param bucket
     * @param filePath
     * @return
     */
    @Override
    public boolean remove(String bucket, String filePath) {
        return getUseStorage().remove(new RemoveFileRequest()
                .setBucket(bucket)
                .setPath(filePath));
    }

    /**
     * 使用阿里云oss处理器
     * @return
     */
    public FileStorageImpl useAliyun() {
        tag.set(StorageTypeEnum.ALIYUN.name().toLowerCase());
        return this;
    }

    /**
     * 使用七牛云oss处理器
     * @return
     */
    public FileStorageImpl useQiniu() {
        tag.set(StorageTypeEnum.QINIU.name().toLowerCase());
        return this;
    }

    /**
     * 使用腾讯云oss处理器
     * @return
     */
    public FileStorageImpl useQcloud() {
        tag.set(StorageTypeEnum.QCLOUD.name().toLowerCase());
        return this;
    }

    /**
     * 使用minio oss处理器
     * @return
     */
    public FileStorageImpl useMinio() {
        tag.set(StorageTypeEnum.MINIO.name().toLowerCase());
        return this;
    }

    /**
     * 使用本地存储处理器
     * @return
     */
    public FileStorageImpl useLocal() {
        tag.set(StorageTypeEnum.LOCAL.name().toLowerCase());
        return this;
    }

    /**
     * 使用自定义oss处理器
     * @return
     */
    public FileStorageImpl useCustom() {
        tag.set(StorageTypeEnum.CUSTOM.name().toLowerCase());
        return this;
    }

    /**
     * 获取选中的文件处理器
     * @return
     */
    private Storage getUseStorage() {
        String useStorage = tag.get();
        String key = StringUtils.isEmpty(useStorage) ? primaryStorage : useStorage;
        AbstractStorage storage = storageMap.get(key);
        tag.remove();
        if (null == storage) {
            throw new StorageException(key + " storage is null");
        }
        return storage;
    }

    @Override
    public void setPrimaryStorage(String primaryStorage) {
        this.primaryStorage = primaryStorage.toLowerCase();
    }

}
